package com.supermap.panes;

import com.supermap.Helper;
import com.supermap.data.*;
import com.supermap.panes.advance.SettingPane;
import com.supermap.realspace.AnalysisMode;
import com.supermap.realspace.DisplayMode;
import com.supermap.realspace.HypsometricSetting;
import com.supermap.realspace.TerrainLayers;
import com.supermap.ui.Action3D;
import com.supermap.ui.SceneControl;
import com.supermap.ui.Tracking3DListener;

import javax.swing.*;
import java.awt.*;
import java.util.HashMap;

public class FloodAnalystPane extends SettingPane {
    private SceneControl sceneControl;

    private JTextField transparencyTxt;
    private JTextField currentVisibleValueTxt;
    private JTextField minVisibleValueTxt;
    private JTextField maxVisibleValueTxt;
    private JTextField totalTimeTxt;
    private JTextField speedTxt;

    private HypsometricSetting hypsometricSetting;
    private Tracking3DListener tracking3DListener = tracking3DEvent -> {
        Geometry3D geometry = tracking3DEvent.getGeometry();
        if (sceneControl.getAction() == Action3D.CREATE_POLYGON && geometry instanceof GeoRegion3D) {
            GeoRegion3D geoRegion3D = (GeoRegion3D) geometry;
            if (geoRegion3D.getPartCount() > 0) {
                generateHypsometricSetting(geoRegion3D);
                sceneControl.getScene().getTerrainLayers().setHypsometricSetting(hypsometricSetting);
                super.confirmBtn.setEnabled(true);
            }
        }
    };

    private Timer floodTimer;

    public FloodAnalystPane(String title, SceneControl sceneControl) {
        super(title, new Object[]{sceneControl});
    }

    @Override
    protected void initializeArgs(Object[] args) {
        sceneControl = (SceneControl) args[0];
    }

    @Override
    protected void initializeCore() {
        this.confirmBtn.setText("播放");
        super.mainPanel.setLayout(new BorderLayout());

        JToolBar toolBar = new JToolBar();
        super.mainPanel.add(toolBar, BorderLayout.NORTH);

        JButton drawRectBtn = new JButton("绘制");
        toolBar.add(drawRectBtn);
        drawRectBtn.addActionListener(e -> {
            sceneControl.setAction(Action3D.CREATE_POLYGON);
            sceneControl.addTrackingListener(tracking3DListener);
        });

        JButton clearBtn = new JButton("清空");
        toolBar.add(clearBtn);
        clearBtn.addActionListener(e -> {
            clearHypsometricLayer();
            super.confirmBtn.setEnabled(false);
        });

        JPanel centerPanel = new JPanel();
        centerPanel.setLayout(new FlowLayout());
        super.mainPanel.add(centerPanel, BorderLayout.CENTER);

        JPanel parametersPanel = new JPanel();
        parametersPanel.setLayout(new GridBagLayout());
        centerPanel.add(parametersPanel);

        parametersPanel.add(new JLabel("透明度(%):"), new GridBagConstraints(0, 0, 1, 1, 1, 1,
                GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, Helper.DefaultInsets, 0, 0));
        transparencyTxt = new JTextField();
        parametersPanel.add(transparencyTxt, new GridBagConstraints(1, 0, 1, 1, 10, 1,
                GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, Helper.DefaultInsets, 0, 0));

        parametersPanel.add(new JLabel("当前高程:"), new GridBagConstraints(0, 1, 1, 1, 1, 1,
                GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, Helper.DefaultInsets, 0, 0));
        currentVisibleValueTxt = new JTextField();
        parametersPanel.add(currentVisibleValueTxt, new GridBagConstraints(1, 1, 1, 1, 10, 1,
                GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, Helper.DefaultInsets, 0, 0));

        parametersPanel.add(new JLabel("最小可见高程:"), new GridBagConstraints(0, 2, 1, 1, 1, 1,
                GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, Helper.DefaultInsets, 0, 0));
        minVisibleValueTxt = new JTextField();
        parametersPanel.add(minVisibleValueTxt, new GridBagConstraints(1, 2, 1, 1, 10, 1,
                GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, Helper.DefaultInsets, 0, 0));

        parametersPanel.add(new JLabel("最大可见高程:"), new GridBagConstraints(0, 3, 1, 1, 1, 1,
                GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, Helper.DefaultInsets, 0, 0));
        maxVisibleValueTxt = new JTextField();
        parametersPanel.add(maxVisibleValueTxt, new GridBagConstraints(1, 3, 1, 1, 10, 1,
                GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, Helper.DefaultInsets, 0, 0));

        parametersPanel.add(new JLabel("总时间(s):"), new GridBagConstraints(0, 4, 1, 1, 1, 1,
                GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, Helper.DefaultInsets, 0, 0));
        totalTimeTxt = new JTextField();
        parametersPanel.add(totalTimeTxt, new GridBagConstraints(1, 4, 1, 1, 10, 1,
                GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, Helper.DefaultInsets, 0, 0));

        parametersPanel.add(new JLabel("速度(m/s):"), new GridBagConstraints(0, 5, 1, 1, 1, 1,
                GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, Helper.DefaultInsets, 0, 0));
        speedTxt = new JTextField();
        parametersPanel.add(speedTxt, new GridBagConstraints(1, 5, 1, 1, 10, 1,
                GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, Helper.DefaultInsets, 0, 0));

        initializeDefaultValues();
    }

    @Override
    protected void doConfirm() {
        double minVisibleValue = Double.parseDouble(minVisibleValueTxt.getText());
        double maxVisibleValue = Double.parseDouble(maxVisibleValueTxt.getText());

        if (floodTimer == null) {
            floodTimer = new Timer(1000, e -> {
                double totalTimeValue = Double.parseDouble(totalTimeTxt.getText());
                double visibleStepValue = (maxVisibleValue - minVisibleValue) / totalTimeValue;
                double currentVisibleValue = Double.parseDouble(currentVisibleValueTxt.getText());
                currentVisibleValueTxt.setText(String.valueOf((int) (currentVisibleValue + visibleStepValue)));
                refreshHypsometricLayer();
                currentVisibleValue = Double.parseDouble(currentVisibleValueTxt.getText());
                super.confirmBtn.setText((int) ((maxVisibleValue - currentVisibleValue) / visibleStepValue) + "s");
                if (currentVisibleValue >= Double.parseDouble(maxVisibleValueTxt.getText())) {
                    floodTimer.stop();
                    currentVisibleValueTxt.setText(maxVisibleValueTxt.getText());
                    super.confirmBtn.setEnabled(true);
                    super.confirmBtn.setText("播放");
                }
            });
        }

        super.confirmBtn.setEnabled(false);
        currentVisibleValueTxt.setText(String.valueOf(minVisibleValue));
        floodTimer.start();
    }

    @Override
    protected void doClose() {
        clearHypsometricLayer();
        for (Component component : getComponents()) {
            component.disable();
        }
    }

    private void initializeDefaultValues() {
        transparencyTxt.setText("50");
        transparencyTxt.addActionListener(e -> refreshHypsometricLayer());
        double minVisibleValue = 0;
        double maxVisibleValue = 90;
        TerrainLayers terrainLayers = sceneControl.getScene().getTerrainLayers();
        for (int i = 0; i < terrainLayers.getCount(); i++) {
            Dataset dataset = terrainLayers.get(i).getDataset();
            if (dataset instanceof DatasetGrid) {
                DatasetGrid datasetGrid = (DatasetGrid) dataset;
                minVisibleValue = datasetGrid.getMinValue();
                maxVisibleValue = datasetGrid.getMaxValue();
            }
        }
        minVisibleValueTxt.setText(String.valueOf(minVisibleValue));
        minVisibleValueTxt.addActionListener(e -> refreshHypsometricLayer());
        maxVisibleValueTxt.setText(String.valueOf(maxVisibleValue));
        maxVisibleValueTxt.addActionListener(e -> refreshHypsometricLayer());
        currentVisibleValueTxt.setText(maxVisibleValueTxt.getText());
        totalTimeTxt.setText("10");
        totalTimeTxt.addActionListener(e -> {
            int time = Integer.parseInt(totalTimeTxt.getText());
            if (time > 0) {
                speedTxt.setText(String.valueOf((Double.parseDouble(maxVisibleValueTxt.getText()) -
                        Double.parseDouble(minVisibleValueTxt.getText())) / time));
            }
        });
        speedTxt.setEnabled(false);
        speedTxt.setText(String.valueOf((maxVisibleValue - minVisibleValue) / Integer.parseInt(totalTimeTxt.getText())));
        super.confirmBtn.setEnabled(false);
    }

    private void refreshHypsometricLayer() {
        if (hypsometricSetting == null) {
            generateHypsometricSetting(null);
        }
        Geometry coverageRegion = hypsometricSetting.getCoverageRegion();
        clearHypsometricLayer();
        generateHypsometricSetting(coverageRegion);
        TerrainLayers terrainLayers = sceneControl.getScene().getTerrainLayers();
        if (coverageRegion != null) {
            terrainLayers.setHypsometricSetting(hypsometricSetting);
        }
    }

    private void generateHypsometricSetting(Geometry geometry) {
        hypsometricSetting = new HypsometricSetting();
        hypsometricSetting.setAnalysisMode(AnalysisMode.CONTOUR_MAP);
        hypsometricSetting.setDisplayMode(DisplayMode.FACE);
        double maxVisibleValue = Double.parseDouble(maxVisibleValueTxt.getText());
        double minVisibleValue = Double.parseDouble(minVisibleValueTxt.getText());
        HashMap<Double, Color> colorTable = new HashMap<>();
        colorTable.put(minVisibleValue, Color.WHITE);
        colorTable.put(maxVisibleValue, Color.BLUE);
        hypsometricSetting.setColorDictTable(colorTable);
        hypsometricSetting.setOpacity(100 - Double.parseDouble(transparencyTxt.getText()));
        hypsometricSetting.setMinVisibleAltitude(Double.parseDouble(minVisibleValueTxt.getText()));
        hypsometricSetting.setMaxVisibleAltitude(Double.parseDouble(currentVisibleValueTxt.getText()));
        if (geometry != null) {
            hypsometricSetting.setCoverageRegion(geometry);
        }
    }

    private void clearHypsometricLayer() {
        if (hypsometricSetting != null) {
            hypsometricSetting.setDisplayMode(DisplayMode.NONE);
        }
        TerrainLayers terrainLayers = sceneControl.getScene().getTerrainLayers();
        terrainLayers.setHypsometricSetting(hypsometricSetting);
        hypsometricSetting = null;
        sceneControl.setAction(Action3D.PAN);
        sceneControl.removeTrackingListener(tracking3DListener);
    }
}
